import { RouteMeta } from 'vue-router'
import type { RouteRecordRaw, RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'

export const Layout = () => import('@/layout/Layout.vue')
export const BasicLayout = () => import('@/basicLayout/BasicLayout.vue')

const modules = import.meta.glob('@/views/*/*.vue', {
  eager: true
})
const loadRouteModule = import.meta.glob(['@/flow/router/index.ts'], {
  eager: true
})
export const loadModule = (defRoute: AppRouteRecordRaw[]): RouteRecordRaw[] => {
  if (loadRouteModule) {
    const list = [...defRoute]
    for (const i in loadRouteModule) {
      const t = loadRouteModule[i]
      if (t != null) {
        mergeRoute(list, t.routes)
        if (t.modules != null) {
          for (const k in t.modules) {
            modules[k] = t.modules[k]
          }
        }
      }
    }
    return list as RouteRecordRaw[]
  }
  return defRoute as RouteRecordRaw[]
}
const mergeRoute = (source: AppRouteRecordRaw[], to: AppRouteRecordRaw[]) => {
  if (to.length === 0) {
    return
  }
  to.forEach((c) => {
    const route = source.find((a) => a.path === c.path)
    if (route == null) {
      source.push(c)
    } else if (c.children != null && c.children.length > 0) {
      if (route.children == null) {
        route.children = []
      }
      mergeRoute(route.children, c.children)
    }
  })
}
const getLayout = (name) => {
  if (name === 'BasicLayout') {
    return BasicLayout
  }
  return Layout
}

const formatDir = (dir, level) => {
  const route: AppCustomRouteRecordRaw = {
    path: dir.RoutePath,
    name: dir.Id,
    component: getLayout(dir.Layout),
    children: [],
    redirect: null,
    meta: {
      id: dir.Id,
      title: dir.Name,
      icon: dir.Icon,
      description: dir.Description
    }
  }
  if (dir.PageParam != null && dir.PageParam.hidden === true) {
    route.meta.hidden = dir.PageParam.hidden
  }
  if (dir.Children && dir.Children.length > 0) {
    route.redirect = dir.Children[0].RoutePath
    const lev = level + 1
    route.children = dir.Children.map((c) => formatPage(c, lev))
  }
  return route
}
export const formatRoutes = (routes, level): AppCustomRouteRecordRaw[] => {
  return routes.map((c) => {
    if (c.PowerType === 1) {
      return formatDir(c, level)
    } else if (c.PowerType === 0 && level === 0) {
      return formatDir(
        {
          Id: 'dir_' + c.Id,
          Children: [c],
          Layout: 'Layout',
          RoutePath: c.RoutePath,
          PageParam: { hidden: true }
        },
        level
      )
    } else {
      return formatPage(c, level)
    }
  })
}
const formatPage = (page, level) => {
  const route: AppCustomRouteRecordRaw = {
    path: page.RoutePath,
    name: page.RouteName,
    component: null,
    redirect: null,
    children: [],
    meta: {
      id: page.Id,
      title: page.Name,
      icon: page.Icon,
      description: page.Description,
      powerType: page.PowerType,
      permission: page.Opt ?? []
    }
  }
  if (page.PageParam != null) {
    const meta: RouteMeta = route.meta
    for (const i in page.PageParam) {
      if (i === 'keepAlive') {
        meta.noCache = page.PageParam.keepAlive == false
      } else if (i in meta) {
        meta[i] = page.PageParam[i]
      } else {
        meta.params = page.PageParam[i]
      }
    }
  }
  const path = '/src/' + page.PagePath + '.vue'
  const t = modules[path]
  if (t != null) {
    route.component = t.default
  }
  if (page.Children != null && page.Children.length > 0) {
    const lev = level + 1
    route.children = formatRoutes(page.Children, lev)
  }
  return route
}

export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
  if (!route) return route
  const { matched, ...opt } = route
  return {
    ...opt,
    matched: (matched
      ? matched.map((item) => ({
          meta: item.meta,
          name: item.name,
          path: item.path
        }))
      : undefined) as RouteRecordNormalized[]
  }
}
